/*
*/
#include "sqlite_io.h"

#include <stdio.h>

#ifdef __linux__
#define   sprintf_s sprintf
#endif
#include "pfunc_print.h"

SqliteIO::SqliteIO(void)
{
	m_bOpen = false;
}

SqliteIO::~SqliteIO(void)
{
	if(m_bOpen)
		Close();
}

bool SqliteIO::Open(char *szFilePath)
{
	if(m_bOpen)
		Close();
	if(szFilePath == NULL)
	{
		Print_WARN("db:%s is NULL\n", szFilePath);
		return false;
	}

	try
	{
		std::string  m_strCurFileName = szFilePath;
		//MoveCurFileToBakDir(m_strCurFileName);
		m_bOpen = open(m_strCurFileName.c_str());
		if (!m_bOpen)
		{
			return m_bOpen;
		}
		std::string sql;
		execDML("begin transaction;");

		if(!tableExists("SA_Data"))
		{
			sql = "CREATE TABLE [SA_Data] (\
				[Dev_Index] Integer,\
				[YC_Index] Integer,\
				[YC_Time] Integer, \
				[YC_Val] FLOAT DEFAULT 0)";
			execDML(sql.c_str());
		}
		execDML("commit transaction;");
		// Print_NOTICE("success open db:%s\n", szFilePath);
	}
	catch (CSQLiteException& e)
	{
		Print_WARN("\nopen db(%s) fail:\n%s\n\n"
			,szFilePath,e.errorMessage ());
		m_bOpen = false;
	}
	return m_bOpen;
};

bool SqliteIO::IsOpen()
{
	return m_bOpen;
};

void SqliteIO::Close()
{
	//printf("\n\n%s | %s | line: %d | Func: %s ",__TIME__,__FILE__,__LINE__,"Close");
	m_bOpen = false;
	close();
};


bool SqliteIO::getSADataQuery(std::list<SADataItem> &_datas,std::set<int> &_devids
	,std::set<int> &_idxs,SAQueryConf _qconf)
{
	if (!IsOpen())
	{
		return false;
	}

	//config sql
	std::list<std::string> _condition;
	if (_qconf.devid >= 0)
	{
		char buf[32] = { 0 };
		sprintf_s(buf, " Dev_Index=%d ", _qconf.devid);
		_condition.push_back(std::string(buf));
	}
	if (_qconf.idx>=0)
	{
		char buf[32] = { 0 };
		sprintf_s(buf, " YC_Index=%d ", _qconf.idx);
		_condition.push_back(std::string(buf));
	}
	if (_qconf.tvStart)
	{
		char sqlbuf[128] = {0};
		sprintf_s(sqlbuf," YC_Time>%lld "
			, _qconf.tvStart);
		_condition.push_back(std::string(sqlbuf));
	}
	if (_qconf.tvStop)
	{
		char sqlbuf[128] = {0};
		sprintf_s(sqlbuf," YC_Time<=%lld "
			, _qconf.tvStop);
		_condition.push_back(std::string(sqlbuf));
	}
	std::string sql = "SELECT Dev_Index,YC_Index,YC_Time,YC_Val FROM SA_Data";
	if(!_condition.empty())
	{
		sql+=" where ";
		std::list<std::string>::iterator it_end = _condition.end();
		it_end--;
		for (std::list<std::string>::iterator it = _condition.begin();
			it != _condition.end();it--) 
		{
			sql += *it;
			if (it != it_end)
			{
				sql += " and ";
			}
		}
	}
	sql += " order by YC_Time Desc";
	if (_qconf.m_limit>0)
	{
		char buf[32] = { 0 };
		sprintf_s(buf, " LIMIT %d ", _qconf.m_limit);
		sql += std::string(buf);
	}
	//get data from table
	// printf("SQL:%s\n", sql.toStdString().c_str());
	try{
		CSQLiteQuery query = execQuery(sql.c_str());
		while(!query.eof())
		{
			SADataItem item;
			item.Dev_Index = static_cast<int>(query.getInt64Field(0));
			item.YC_Index = static_cast<int>(query.getInt64Field(1));
			item.Time = query.getInt64Field(2);
			item.Value = static_cast<float>(query.getFloatField(3));
			item.ToQT();
			_datas.push_back(item);
			_idxs.insert(item.Dev_Index);
			_idxs.insert(item.YC_Index);
			query.nextRow();
		}
	}catch (CSQLiteException& e)
	{
		Print_WARN("GetSAData FROM SA_Data TABLE ERROR: %s \n", e.errorMessage());
		return false;
	}
	return !_datas.empty();
}

long long SqliteIO::GetLastFT(void)
{
	long long llLast = 0;
	if(m_bOpen)
	{
		CSQLiteQuery query = execQuery("select YC_Time from SA_Data order by YC_Time DESC limit 1");
		if(!query.eof())
			llLast = query.getInt64Field(0);
	}
	return llLast;
};



bool SqliteIO::AddYARecorder(std::list<SADataItem> &_datas)
{
	bool bRet = true;
	try {
		execDML("BEGIN TRANSACTION");
		for (std::list<SADataItem>::iterator it = _datas.begin();
			it != _datas.end(); it++)
		{
			CSQLiteStatement stmt = compileStatement("INSERT INTO SA_Data(Dev_Index,YC_Index,YC_Time,YC_Val) VALUES (?,?,?,?)");
			stmt.bind(1, (*it).Dev_Index);
			stmt.bind(2, (*it).YC_Index);
			stmt.bind(3, (*it).Time);
			stmt.bind(4, (*it).Value);
			stmt.execDML();
		}
		bRet = (execDML("COMMIT TRANSACTION") == 1);
	}catch (CSQLiteException& e)
	{
		execDML("ROLLBACK TRANSACTION");
		Print_WARN("Save Raw Data Failed %s\n", e.errorMessage());
		bRet = false;
	}

	return bRet;
};
